package actors

import akka.actor.typed.ActorRef
import spray.json._

object Messages {
  // states
  final case class Registration(id: String, name: String)
  final case class CameraDevice(id: String,                       // device unique identifier
                                name: String,                     // device name
                                manufacturer: String = "default", // relative manufacturer
                                quality: String = "high",         // stream quality
                                width: Int = 640,                 // picture width
                                height: Int = 480,                // picture height
                                streamURL: String,                // upstream URL - "<protocol>://<domain>[:port]/live/<id>"
                                status: String = "active",        // active / down / offline
                                onlineTime: String,               // time of which goes online
                                offlineTime: String,              // time of which goes offline
                                frameRate: Int = 30,              // video frame rate, with maximum at 30fps
                                bitRate: Int = 5000000)           // video bit rate in bps

  trait CameraDeviceJsonProtocol extends DefaultJsonProtocol {
    implicit val cameraDeviceFormat: RootJsonFormat[CameraDevice] = jsonFormat12(CameraDevice)
  }

  // Master Protocol
  sealed trait MasterProtocol
  // Requests
  final case class RegisterDevice(user: String, name: String, replyTo: ActorRef[UserProtocol]) extends MasterProtocol
  final case class UpdateDeviceInfo(id: String, property: String, value: String, replyTo: ActorRef[UserProtocol]) extends MasterProtocol
  final case class GetDeviceInfo(id: String, replyTo: ActorRef[UserProtocol]) extends MasterProtocol
  final case class UnregisterDevice(id: String, replyTo: ActorRef[UserProtocol]) extends MasterProtocol
  final case class ShowDevicesList(replyTo: ActorRef[UserProtocol]) extends MasterProtocol

  // Device Protocol
  sealed trait DeviceProtocol
  final case class DeviceRegisterTask(newDevice: CameraDevice, replyTo: ActorRef[UserProtocol]) extends DeviceProtocol
  final case class DeviceGetInfoTask(replyTo: ActorRef[UserProtocol]) extends DeviceProtocol
  final case class DeviceUpdateInfoTask(property: String, value: String, replyTo: ActorRef[UserProtocol]) extends DeviceProtocol
  final case class DeviceUnregisterTask(id: String, replyTo: ActorRef[UserProtocol]) extends DeviceProtocol
  final case class ReplyTask(ack: UserProtocol, replyTo: ActorRef[UserProtocol]) extends DeviceProtocol

  // User Protocol
  sealed trait UserProtocol
  // Replies
  final case class DeviceRegisteredResponse(newCamera: CameraDevice) extends UserProtocol
  final case class DeviceInfoUpdatedResponse(updatedCamera: CameraDevice) extends UserProtocol
  final case class GetDeviceInfoResponse(deviceInfo: CameraDevice) extends UserProtocol
  final case object DeviceUnregisterResponse extends UserProtocol
  final case class RegistrationFailure(reason: Throwable) extends UserProtocol
  final case class ExecutionFailed(reason: Throwable) extends UserProtocol
  final case class ShowDevicesResponse(devices: Map[String, ActorRef[DeviceProtocol]]) extends UserProtocol
}
